# -*- coding: utf-8 -*-
"""
    Created by huangyi at 2020/7/30.
    Description:
    Changelog: all notable changes to this file will be documented
"""
from ..expression.nonterminal.func.between import Between
from ..expression.nonterminal.func.list import List
from ..ast.ast import Ast
from ..expression.abs_expression import AbsExpression
from ..expression.context import Context
from ..expression.nonterminal.func.func import Func
from ..expression.nonterminal.func.sqrt import Sqrt
from ..expression.nonterminal.func.sum import Sum
from ..scanner.scanner import Scanner


def new():
    runtime = Runtime()
    return runtime


class Runtime:

    def __init__(self):
        self.func_dict = {}
        self.load_func()

    def exec(self, expression: str, data: dict = None):
        exp = self.parse(expression)
        return self.run(exp, data)

    def run(self, exp_ast: AbsExpression, data: dict = None):
        ctx = self._create_ctx()
        if data:
            ctx.data.update(data)
        if exp_ast:
            return exp_ast.interpret(ctx)

    def parse(self, expression: str):
        scanner = Scanner()
        ast = Ast()
        if not expression:
            return None
        token_list = scanner.scan(expression)
        exp = ast.parse(token_list)
        return exp

    def _create_ctx(self) -> Context:
        ctx = Context()
        ctx.func_dict = self.func_dict
        return ctx

    def load_func(self):
        self.add_func(Sum())
        self.add_func(Sqrt())
        self.add_func(List())
        self.add_func(Between())

    def add_func(self, func: Func):
        if func:
            self.func_dict[func.get_name()] = func
